<script>
import {defineComponent, h} from 'vue';
import SignaturePad from 'signature_pad';

export default defineComponent({
  name: 'VueSignaturePad',
  props: {
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '100%'
    },
    customStyle: {
      type: Object,
      default: () => ({})
    },
    options: {
      type: Object,
      default: () => ({})
    },
    images: {
      type: Array,
      default: () => []
    },
    scaleToDevicePixelRatio: {
      type: Boolean,
      default: () => true
    }
  },

  data: () => ({
    signaturePad: {},
    cacheImages: [],
    signatureData: null,
    onResizeHandler: null
  }),

  watch: {
    options: function (nextOptions) {
      Object.keys(nextOptions).forEach(option => {
        if (this.signaturePad[option]) {
          this.signaturePad[option] = nextOptions[option];
        }
      });
    }
  },

  mounted() {
    const { options } = this;
    const canvas = this.$refs.signaturePadCanvas;
    this.signaturePad = new SignaturePad(canvas, {
      ...options
    });

    if (options.resizeHandler) {
      this.resizeCanvas = options.resizeHandler.bind(this);
    }

    this.onResizeHandler = this.resizeCanvas.bind(this);

    window.addEventListener('resize', this.onResizeHandler, false);

    this.resizeCanvas();
  },

  beforeUnmount() {
    if (this.onResizeHandler) {
      window.removeEventListener('resize', this.onResizeHandler, false);
    }
  },

  methods: {
    resizeCanvas() {
      this.$nextTick(() => {
        const canvas = this.$refs.signaturePadCanvas;
        const data = this.signaturePad.toData();
        const ratio = this.scaleToDevicePixelRatio
          ? Math.max(window.devicePixelRatio || 1, 1)
          : 1;

        canvas.width = canvas.offsetWidth * ratio;
        canvas.height = canvas.offsetHeight * ratio;
        canvas.getContext('2d').scale(ratio, ratio);

        this.signaturePad.clear();
        this.signaturePad.fromData(data);
      })
    },

    saveSignature() {
      const { signaturePad } = this;
      const status = { isEmpty: false, data: undefined };

      if (signaturePad.isEmpty()) {
        return {
          ...status,
          isEmpty: true
        };
      } else {
        this.signatureData = this.getDraw();

        return {
          ...status,
          data: this.signatureData
        };
      }
    },

    getDraw() {
      const canvas = this.$refs.signaturePadCanvas;
      const ctx = canvas.getContext("2d");

      // 获取画布的像素数据
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      const pixels = imageData.data;

      // 找到非空白区域的边界
      let minX = canvas.width, minY = canvas.height;
      let maxX = 0, maxY = 0;

      for (let y = 0; y < canvas.height; y++) {
        for (let x = 0; x < canvas.width; x++) {
          const index = (y * canvas.width + x) * 4;
          if (pixels[index + 3] > 0) { // 如果像素不透明
            if (x < minX) minX = x;
            if (x > maxX) maxX = x;
            if (y < minY) minY = y;
            if (y > maxY) maxY = y;
          }
        }
      }

      // 如果没有找到非空白区域，直接返回
      if (minX === canvas.width || minY === canvas.height) {
        console.warn("没有找到绘画内容。");
        return;
      }

      // 创建一个新的画布用于裁剪
      const croppedCanvas = document.createElement("canvas");
      croppedCanvas.width = maxX - minX;
      croppedCanvas.height = maxY - minY;
      const croppedCtx = croppedCanvas.getContext("2d");
      croppedCtx.fillStyle = "white";
      croppedCtx.fillRect(0, 0, croppedCanvas.width, croppedCanvas.height);
      // 将非空白区域绘制到新的画布上
      croppedCtx.drawImage(canvas, minX, minY, croppedCanvas.width, croppedCanvas.height, 0, 0, croppedCanvas.width, croppedCanvas.height);

      // 更新签名画布
      return croppedCanvas.toDataURL();
    },

    undoSignature() {
      const { signaturePad } = this;
      const record = signaturePad.toData();

      if (record) {
        return signaturePad.fromData(record.slice(0, -1));
      }
    },

    fromDataURL(data, options = {}, callback) {
      return this.signaturePad.fromDataURL(data, options, callback);
    },

    fromData(data) {
      return this.signaturePad.fromData(data);
    },

    toData() {
      return this.signaturePad.toData();
    },

    lockSignaturePad() {
      return this.signaturePad.off();
    },

    openSignaturePad() {
      return this.signaturePad.on();
    },

    isEmpty() {
      return this.signaturePad.isEmpty();
    },

    clearCacheImages() {
      this.cacheImages = [];

      return this.cacheImages;
    },

    clearSignature() {
      return this.signaturePad.clear();
    }
  },

  render() {
    const { width, height, customStyle } = this;

    return h(
      'div',
      {
        style: {
          width,
          height,
          ...customStyle
        }
      },
      [
        h('canvas', {
          style: {
            width: width,
            height: height
          },
          ref: 'signaturePadCanvas'
        })
      ]
    );
  }
});
</script>
